package com.xuecheng.auth.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xuecheng.auth.service.AuthService;
import com.xuecheng.auth.service.WxAuthService;
import com.xuecheng.ucenter.mapper.XcUserMapper;
import com.xuecheng.ucenter.mapper.XcUserRoleMapper;
import com.xuecheng.ucenter.model.dto.AuthParamsDto;
import com.xuecheng.ucenter.model.dto.XcUserExt;
import com.xuecheng.ucenter.model.po.XcUser;
import com.xuecheng.ucenter.model.po.XcUserRole;
import lombok.SneakyThrows;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

/**
 * @author Tang
 * @version 1.0
 * @date 2024/1/11 21:02
 */
@Service("wx_authservice")
public class WxAuthServiceImpl implements AuthService, WxAuthService {
    @Value("${weixin.appid}")
    String appid;
    @Value("${weixin.secret}")
    String secret;
    @Autowired
    private XcUserMapper xcUserMapper;
    @Autowired
    private XcUserRoleMapper xcUserRoleMapper;
    @Autowired
    private WxAuthService currentProxy;
    @Autowired
    private RestTemplate restTemplate;
    private final static String WX_GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
    private final static String WX_GET_USER_INFO_URL = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s";
    @Override
    public XcUserExt execute(AuthParamsDto authParamsDto) {
        XcUser xcUser = xcUserMapper.selectOne(new LambdaQueryWrapper<XcUser>()
                .eq(XcUser::getId,
                new String(authParamsDto.getUsername().getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8)));
        if (Objects.isNull(xcUser)) {
            throw new RuntimeException("用户不存在");
        }
        XcUserExt userExt = new XcUserExt();
        BeanUtils.copyProperties(xcUser, userExt);
        return userExt;
    }

    @SneakyThrows
    @Override
    public XcUser wxAuth(String code) {
        // 申请令牌
        Map<String, String> accessToken = getAccessToken(code);
        // 携带令牌查询用户信息
        Map<String, String> userInfo = getUserInfo(accessToken.get("access_token"), accessToken.get("openid"));
        return currentProxy.userInfoToDataBase(userInfo);
    }

    @Override
    @Transactional
    public XcUser userInfoToDataBase(Map<String, String> userInfo) {
        String unionid = userInfo.get("unionid");
        XcUser xcUser = xcUserMapper.selectOne(new LambdaQueryWrapper<XcUser>().eq(XcUser::getWxUnionid, unionid));
        if (Objects.isNull(xcUser)) {
            XcUser user = new XcUser();
            String nickname = userInfo.get("nickname");
            user.setId(UUID.randomUUID().toString());
            user.setUsername(nickname);
            user.setPassword(unionid);
            user.setWxUnionid(unionid);
            user.setNickname(nickname);
            user.setName(nickname);
            user.setUtype("101001");
            user.setStatus("1");
            user.setCreateTime(LocalDateTime.now());
            xcUserMapper.insert(user);
            // 向用户角色关系表写数据
            XcUserRole xcUserRole = new XcUserRole();
            xcUserRole.setId(UUID.randomUUID().toString());
            xcUserRole.setUserId(user.getId());
            // 表示学生角色
            xcUserRole.setRoleId("17");
            xcUserRole.setCreateTime(LocalDateTime.now());
            xcUserRoleMapper.insert(xcUserRole);
            return user;
        }
        return xcUser;
    }

    public Map<String, String> getUserInfo(String accessToken, String openId) throws UnsupportedEncodingException {
        String url = String.format(WX_GET_USER_INFO_URL, accessToken, openId);
        ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.POST, null, String.class);
        String body = exchange.getBody();
        return JSON.parseObject(new String(body.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8), Map.class);
    }

    public Map<String, String> getAccessToken(String code) {
        String url = String.format(WX_GET_ACCESS_TOKEN_URL, appid, secret, code);
        ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.POST, null, String.class);
        // 获取响应结果
        String body = exchange.getBody();
        return JSON.parseObject(body, Map.class);
    }
}
